import {
  BadRequestException,
  ExceptionFilter,
  HttpAdapterHost,
  HttpException,
  HttpStatus,
  LoggerService,
  UnauthorizedException,
} from '@nestjs/common';
import { ArgumentsHost, Catch } from '@nestjs/common';

import * as requestIp from 'request-ip';
import { QueryFailedError } from 'typeorm';
import { ResultUtils } from '../utils/result.utils';

@Catch()
export class AllExceptionFilter implements ExceptionFilter {
  constructor(
    private readonly logger: LoggerService,
    private readonly httpAdapterHost: HttpAdapterHost,
  ) {}
  catch(exception: unknown, host: ArgumentsHost) {
    let message = ''
    const { httpAdapter } = this.httpAdapterHost;
    const ctx = host.switchToHttp();
    const request = ctx.getRequest();
    const response = ctx.getResponse();

    const httpStatus =
      exception instanceof HttpException
        ? exception.getStatus()
        : HttpStatus.INTERNAL_SERVER_ERROR;
    
    let msg:string = exception['response'] || 'Internal Server Error'
    if(exception instanceof QueryFailedError) {
      msg = exception.message
    }else if(exception instanceof BadRequestException) {
      interface BadRequestExceptionMessage {
        message:Array<string>|string;
        statusCode:number;
        error:string;
      }
      const exceptioinResponse:BadRequestExceptionMessage = exception.getResponse() as BadRequestExceptionMessage
      if(exceptioinResponse.message instanceof Array) {
        message = exceptioinResponse.message[0]
      }else {
        message = exceptioinResponse.message
      } 
    }else if(exception instanceof UnauthorizedException){
      message = '未登录'
    }else if(exception instanceof HttpException){
      message = exception.getResponse() as string
    }

    const responseBody = {
      headers: request.headers,
      query: request.query,
      body: request.body,
      params: request.params,
      timestamp: new Date().toISOString(),
      // 还可以加入一些用户信息
      // IP信息
      ip: requestIp.getClientIp(request),
      exceptioin: exception['name'],
      error: msg,
    };

    this.logger.error('[toimc]', responseBody);
    httpAdapter.reply(response, ResultUtils.error(httpStatus,message), 200);
  }
}
